package sparql;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import application.Parametres;
import bdd.GetBDD;

import modele.Noeud;
import modele.Terme;
import parsage.Lemmatiseur;
import requetes.LancerRequete;
import requetes.ListeTermesEtPoids;
import requetes.ResultatRequete;
import stopList.StopList;

/**
 * 
 * @author Florence Delrieu & Coralie Micouin
 * 
 */
public class TraiterOntologie {

	/**
	 * Methode lemmatisant un label (mot ou groupe de mot)
	 * 
	 * @param label
	 *            : label a lemmatiser
	 * @param sparqlClient
	 *            nous permet d'appeler ask
	 * @return : Si label lemmatise n'existe pas deja on retourne le label
	 *         lemmatise sinon on retourne la chaine vide ""
	 */
	public static String lemmatiserLabel(String label,
			RequeteOntologie sparqlClient) {
		String labelLemmatise = "";
		ArrayList<String> vecteurDuLabel = new ArrayList<String>();

		vecteurDuLabel = Lemmatiseur.decoupeChaine(label, true);
		boolean labelExiste = false;
		StopList stopListe = new StopList("ressources/stopliste.txt");

		// on met le vecteur de mots lemmatises du label dans un string
		labelLemmatise = "";
		for (int i = 0; i < vecteurDuLabel.size(); i++) {
			// On enleve les mots de la stop liste
			if (!stopListe.getStopListe().contains(vecteurDuLabel.get(i))) {
				if (i < vecteurDuLabel.size() - 1) // pas dernier mot
					labelLemmatise += vecteurDuLabel.get(i) + " ";
				else
					labelLemmatise += vecteurDuLabel.get(i);
			}
		}
		String query = "PREFIX : <http://ontologies.alwaysdata.net/space#> "
				+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
				+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
				+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
				+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
				+ "ASK WHERE {" + "	?class rdfs:label \"" + labelLemmatise
				+ "\"@fr." + "	?class rdfs:label \"" + label + "\"@fr.}";
		labelExiste = sparqlClient.ask(query);

		if (labelExiste)
			labelLemmatise = "";

		return labelLemmatise;
	}

	/**
	 * Lemmatise une ontologie (c'est-a-dire tous les labels) : insere les
	 * nouveaux labels lemmatises (s'ils n'existent pas deja)
	 * 
	 * @param sparqlClient
	 *            nous permet d'appeler insert
	 */
	public static void lemmatiserOntologie(RequeteOntologie sparqlClient) {
		Iterable<Map<String, String>> labels = getLabels(sparqlClient);
		String labelLemmatise = "";

		String lemmatiserOntologieQuery = "";
		for (Map<String, String> result : labels) {
			// Attention on ne doit pas lemmatiser les paragraphes !!!
			if (!result.get("label").contains(".xml")) {
				labelLemmatise = TraiterOntologie.lemmatiserLabel(
						result.get("label"), sparqlClient);

				// si la lemmatisation a cree un label different et qui n'existe
				// pas deja, on l'ajoute

				// <=> si le label n'existe pas deja
				if (!labelLemmatise.equals("")) {
					lemmatiserOntologieQuery = "PREFIX : <http://ontologies.alwaysdata.net/space#> "
							+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
							+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
							+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
							+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
							+ "INSERT{"
							+ "	?class rdfs:label \""
							+ labelLemmatise
							+ "\"@fr."
							+ "}"
							+ "WHERE{"
							+ "	?class rdfs:label \""
							+ result.get("label")
							+ "\"@fr." + "}";
					sparqlClient.update(lemmatiserOntologieQuery);
				}
			}
		}
	}

	/**
	 * Recupere tous les labels d'une ontologie
	 * 
	 * @param sparqlClient
	 *            nous permet d'appeler SELECT
	 * @return les labels
	 */
	public static Iterable<Map<String, String>> getLabels(
			RequeteOntologie sparqlClient) {
		String getLabelsQuery = "PREFIX : <http://ontologies.alwaysdata.net/space#> "
				+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
				+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
				+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
				+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
				+ "SELECT ?label "
				+ "WHERE {"
				+ "   ?class rdfs:label ?label."
				+ "}";
		Iterable<Map<String, String>> results = sparqlClient
				.select(getLabelsQuery);
		for (Map<String, String> result : results) {
			System.out.println(result.get("label"));
		}
		return results;
	}

	/**
	 * Prend en entree une requete et cree des sous requetes a chercher en
	 * diminuant la taille de la fenetre
	 * 
	 * @param requete
	 *            : requete de l'utilisateur
	 * @return une liste de sous requetes et leur poids
	 */
	public static SousRequetesPonderees gererFenetres(String requete) {
		// On lemmatise la requete
		ArrayList<String> vecteurRequete = Lemmatiseur.decoupeChaine(requete,
				false);
		String labelCourant = "";

		// toutes les requetes des fenetres => ce qui est retourne par la
		// methode
		ArrayList<String> listeSousRequetes = new ArrayList<String>();
		ArrayList<Integer> listePoids = new ArrayList<Integer>();
		ArrayList<Integer> listeIndicesDebut = new ArrayList<Integer>();
		ArrayList<Integer> listeIndicesFin = new ArrayList<Integer>();

		// On diminue la fenetre de 1 en 1
		for (int tailleFenetre = vecteurRequete.size(); tailleFenetre > 0; tailleFenetre--) {
			// on deplace la fenetre
			for (int j = 0; j <= (vecteurRequete.size() - tailleFenetre); j++) {
				labelCourant = "";
				for (int i = j; i < j + tailleFenetre; i++) {
					if (i < j + tailleFenetre - 1)
						labelCourant += vecteurRequete.get(i) + " ";
					else
						labelCourant += vecteurRequete.get(i);
				}
				int poids = tailleFenetre;
				if (Parametres.REQUETE_PONDEREE) {
					poids *= (vecteurRequete.size() - j);
				}
				listeSousRequetes.add(labelCourant);
				listePoids.add(poids);
				listeIndicesDebut.add(j);
				listeIndicesFin.add(j + tailleFenetre - 1);
			}
		}
		return new SousRequetesPonderees(listeSousRequetes, listePoids,
				listeIndicesDebut, listeIndicesFin);
	}

	/**
	 * Fonction d'epuration d'une liste de fenetres (des sous requetes)
	 * 
	 * @param listeSousReqOrig
	 * @param listePoidsOrig
	 * @param listeIndicesDebutOrig
	 * @param listeIndicesFinOrig
	 * @param sousReqChoisie
	 * @return
	 */
	public static SousRequetesPonderees epurerFenetres(
			ArrayList<String> listeSousReqOrig,
			ArrayList<Integer> listePoidsOrig,
			ArrayList<Integer> listeIndicesDebutOrig,
			ArrayList<Integer> listeIndicesFinOrig, String sousReqChoisie) {

		ArrayList<String> listeSousRequetes = new ArrayList<String>();
		ArrayList<Integer> listePoids = new ArrayList<Integer>();
		ArrayList<Integer> listeIndicesDebut = new ArrayList<Integer>();
		ArrayList<Integer> listeIndicesFin = new ArrayList<Integer>();

		// recuperation des indices de debut et fin de la sous requete dans la
		// requete d'origine
		int indiceSousReq = listeSousReqOrig.indexOf(sousReqChoisie);
		int debut = listeIndicesDebutOrig.get(indiceSousReq);
		int fin = listeIndicesFinOrig.get(indiceSousReq);
		System.out.println("On epure la sous requete \"" + sousReqChoisie
				+ "\" ; debut = " + debut + " et fin = " + fin);

		// Pour chaque sous requete restante :
		for (int i = 0; i < listeSousReqOrig.size(); i++) {
			// Si elle n'est pas en intersection avec la sous requete a
			// supprimer
			if ((listeIndicesDebutOrig.get(i) > fin)
					|| (listeIndicesFinOrig.get(i) < debut)) {
				// On la conserve, ainsi que son poids et ses indices de debut
				// et fin
				listeSousRequetes.add(listeSousReqOrig.get(i));
				listePoids.add(listePoidsOrig.get(i));
				listeIndicesDebut.add(listeIndicesDebutOrig.get(i));
				listeIndicesFin.add(listeIndicesFinOrig.get(i));
			}
		}
		return new SousRequetesPonderees(listeSousRequetes, listePoids,
				listeIndicesDebut, listeIndicesFin);
	}

	/**
	 * Prend en entree une sous requete donnee par une fenetre et recupere les
	 * labels synonymes
	 * 
	 * @param requete
	 *            : sous requete donnee par une fenetre
	 * @param sparqlClient
	 *            nous permet d'appeler SELECT
	 * @return la liste des labels synonymes
	 */
	public static Iterable<Map<String, String>> lanceRequeteSynonymes(
			String requete, RequeteOntologie sparqlClient) {
		String getSynonymesQuery = "PREFIX : <http://ontologies.alwaysdata.net/space#>"
				+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
				+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
				+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
				+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
				+ "SELECT ?name"
				+ "	WHERE {"
				+ "		?mot rdfs:label \""
				+ requete
				+ "\"@fr."
				+ "		?mot rdfs:label ?name"
				+ "		FILTER ( ?name !=  \"" + requete + "\"@fr )" + "	}";

		Iterable<Map<String, String>> results = sparqlClient
				.select(getSynonymesQuery);
		return results;
	}

	/**
	 * Prend en entree une sous requete donnee par une fenetre et recupere les
	 * instances d'un label (exemple : mammifere)
	 * 
	 * @param requete
	 *            : sous requete donnee par une fenetre
	 * @param sparqlClient
	 *            nous permet d'appeler SELECT
	 * @return la liste des labels instances
	 */
	public static Iterable<Map<String, String>> lanceRequeteInstancesClasse(
			String requete, RequeteOntologie sparqlClient) {
		String getInstancesClasseQuery = "PREFIX : <http://ontologies.alwaysdata.net/space#>"
				+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
				+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
				+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
				+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
				+ "SELECT ?name"
				+ "	WHERE {"
				+ "		?class rdfs:label \""
				+ requete
				+ "\"@fr."
				+ "		?mot rdf:type ?class."
				+ "		?mot rdfs:label ?name." + "	}";
		Iterable<Map<String, String>> results = sparqlClient
				.select(getInstancesClasseQuery);
		return results;
	}

	/**
	 * Prend en entree une sous requete donnee par une fenetre et recupere les
	 * sous classes d'un label (exemple : mammifere)
	 * 
	 * @param requete
	 *            : sous requete donnee par une fenetre
	 * @param sparqlClient
	 *            nous permet d'appeler SELECT
	 * @return la liste des labels sous classe
	 */
	public static Iterable<Map<String, String>> lanceRequeteSubClasses(
			String requete, RequeteOntologie sparqlClient) {
		String getSubClassesQuery = "PREFIX : <http://ontologies.alwaysdata.net/space#>"
				+ "PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
				+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
				+ "PREFIX owl:  <http://www.w3.org/2002/07/owl#>"
				+ "PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>"
				+ "SELECT ?name"
				+ "	WHERE {"
				+ "		?class rdfs:label \""
				+ requete
				+ "\"@fr."
				+ "		?mot rdfs:subClassOf ?class."
				+ "		?mot rdfs:label ?name." + "	}";

		Iterable<Map<String, String>> results = sparqlClient
				.select(getSubClassesQuery);

		return results;
	}

	/**
	 * TODO CORRIGER JAVADOC Retourne les noeuds les plus pertinents pour la
	 * requete
	 * 
	 * @param requeteAmelioree
	 *            sous forme d'ArrayList de String (=mot)
	 * @param seuilPertinence
	 *            : nombre de resultats retournes ou tous les resultats si
	 *            seuilPertinence = -1
	 * @return les noeuds pertinents et leurs scores
	 * @throws Exception
	 *             si lors d'un appel a cos, les deux entrees ne sont pas de
	 *             meme longueur
	 */
	public static ResultatRequete resultatRequete(
			Map<String, Integer> requeteAmelioree, int seuilPertinence)
			throws Exception {
		ArrayList<Noeud> noeudsPertinents = new ArrayList<Noeud>();

		ArrayList<Terme> vecteurRequete = new ArrayList<Terme>();
		ArrayList<Double> vecteurPoids = new ArrayList<Double>();

		for (String sousReq : requeteAmelioree.keySet()) {

			int poidsSousReq = requeteAmelioree.get(sousReq);

			// Recuperation des termes et poids de cette requete
			// Cette fois on considere les mots comme des labels
			// ("aPourDistance" a decouper en 3 mots "a pour distance")
			// Par contre, on ne donne pas plus de poids aux premiers mots d'un
			// synonymes qu'a ses derniers, donc pas de ponderation dans le
			// calcul des poids des termes
			ListeTermesEtPoids listeTermesEtPoids = LancerRequete
					.getTermesRequete(sousReq, false, true);
			ArrayList<Terme> vecteurTermes = listeTermesEtPoids
					.getListeTermes();

			for (Terme terme : vecteurTermes) {
				if (vecteurRequete.contains(terme)) {
					int indiceTerme = vecteurRequete.indexOf(terme);
					vecteurPoids.set(indiceTerme, vecteurPoids.get(indiceTerme)
							+ poidsSousReq);
				} else {
					vecteurRequete.add(terme);
					vecteurPoids.add((double) poidsSousReq);
				}
			}

		}

		ArrayList<ArrayList<Double>> vecteursScores = new ArrayList<ArrayList<Double>>();
		ArrayList<Double> vecteurCosinus = new ArrayList<Double>();
		boolean triModifie = true; // boolean pour tri a bulles

		// juste un print des termes
		System.out.println("Liste des termes de la requete :");
		for (int t = 0; t < vecteurRequete.size(); t++) {
			Terme terme = vecteurRequete.get(t);
			double poids = vecteurPoids.get(t);
			System.out.println(" -> \"" + terme.getTerme() + "\" de poids "
					+ poids + " dans la requete");
		}

		// recuperer tous les noeuds dans noeudsPertinents
		noeudsPertinents = LancerRequete.getNoeudRequete(vecteurRequete);
		System.out.println("Lors de la requete, " + noeudsPertinents.size()
				+ " noeuds pertinents ont ete trouves");

		// boucle sur les noeuds et remplit vecteursScores avec les resultats de
		// getScoresParNoeudAPartirRequete
		System.out
				.println("Calcul du score de chaque noeud par rapport a chaque terme de la requete");
		for (int i = 0; i < noeudsPertinents.size(); i++) {
			vecteursScores.add(LancerRequete.getScoresParNoeudAPartirRequete(
					vecteurRequete, noeudsPertinents.get(i).getIdNoeud()));
		}

		System.out
				.println("Calcul du score de chaque noeud par rapport a la requete");

		// calculer le produit scalaire (avec la formule du cosinus) pour
		// chaque noeud
		for (int i = 0; i < noeudsPertinents.size(); i++) {
			if (Parametres.UTILISE_COS) {
				vecteurCosinus.add(LancerRequete.cos(vecteursScores.get(i),
						vecteurPoids));
			} else {
				vecteurCosinus.add(LancerRequete.scalaire(
						vecteursScores.get(i), vecteurPoids));
			}
		}

		System.out
				.println("Les scores sont calcules pour chaque noeud, il faut trier la liste dans l'ordre des scores decroissants");

		// classer ces resultats par ordre decroissant
		// les associer aux noeuds pour pouvoir les renvoyer
		while (triModifie) {
			triModifie = false;
			for (int j = 0; j < noeudsPertinents.size() - 1; j++) {
				// si deux noeuds consecutifs ne sont pas dans le bon ordre on
				// les swap
				if (vecteurCosinus.get(j) < vecteurCosinus.get(j + 1)) {
					// swapDouble(vecteurCosinus, j, j+1);
					Collections.swap(vecteurCosinus, j, j + 1);
					// swapNoeud(noeudsPertinents, j, j+1);
					Collections.swap(noeudsPertinents, j, j + 1);
					triModifie = true;
				}
			}
		}

		System.out
				.println("On a trie la liste des noeuds pertinents, on la tronque");

		// si un seuil est defini :
		if (seuilPertinence > 0) {
			// et ne garder que les pertinents
			int nbASupprimer = noeudsPertinents.size() - seuilPertinence;
			for (int i = 0; i < nbASupprimer; i++) {
				noeudsPertinents.remove(seuilPertinence);
				vecteurCosinus.remove(seuilPertinence);
			}
		}
		System.out.println("Apres troncature, elle contient "
				+ noeudsPertinents.size() + " noeuds");
		return new ResultatRequete(noeudsPertinents, vecteurCosinus);
	}

	/**
	 * Fonction intermediaire construisant une requete amelioree a partir d'une
	 * requete adressee a l'ontologie. On cherche les synonymes et sous classes
	 * des termes de cette requete, pour ecrire une requete plus complexe
	 * adressee a la base de termes, pour une recherche "standard"
	 * 
	 * @param requete
	 *            la requete a traiter
	 * @return une requete amelioree
	 */
	public static Map<String, Integer> construitRequeteStandardDepuisOntologie(
			String requete) {
		boolean sousReqTrouvee = false;
		String sousReq = null;
		ArrayList<String> listeSyno = new ArrayList<String>();
		ArrayList<String> listeSubclass = new ArrayList<String>();
		RequeteOntologie sparqlClient = new RequeteOntologie(
				"localhost:3030/space");

		// Calcul des fenetres initiales (des sous requetes)
		SousRequetesPonderees sousReqPonderees = gererFenetres(requete);
		ArrayList<String> listeSousReq = sousReqPonderees.getSousRequetes();
		ArrayList<Integer> listePoids = sousReqPonderees.getPoids();
		ArrayList<Integer> listeIndicesDebut = sousReqPonderees
				.getIndicesDebut();
		ArrayList<Integer> listeIndicesFin = sousReqPonderees.getIndicesFin();

		// Et voici la requete amelioree. Il s'agit en fait d'une liste de sous
		// requetes avec des poids associes. Ainsi, si l'on cherche
		// "balade Pyrenees", et que la recherche par fenetres separe "balade"
		// et "Pyrenees", puis trouve leurs synonymes "balade randonnee"
		// "Pyrenees", alors "balade" et "randonnee" auront un poids plus fort
		// que "Pyrenees" car plus proches du debut de la requete (du moins si
		// on utilise cette option)
		Map<String, Integer> requeteAmelioree = new HashMap<String, Integer>();

		// Tant qu'il reste des sous requetes a tester
		while (!listeSousReq.isEmpty()) {

			// On prend la plus longue (on les a triees dans l'ordre
			// decroissant)
			sousReq = listeSousReq.get(0);
			sousReqTrouvee = false;

			// Recherche de synonymes
			System.out.println(">> Recherche des synonymes dans la fenetre : "
					+ sousReq);
			Iterable<Map<String, String>> sousListeSyno = TraiterOntologie
					.lanceRequeteSynonymes(sousReq, sparqlClient);

			// Les synonymes sont stockes
			if (sousListeSyno.iterator().hasNext()) {
				sousReqTrouvee = true;
				System.out.print("  resultats -> ");
				for (Map<String, String> result : sousListeSyno) {
					listeSyno.add(result.get("name"));
					System.out.print(result.get("name") + " -- ");
				}
				System.out.println();
			}

			// Recherche de sous classes
			System.out
					.println(">> Recherche des sous classes dans la fenetre : "
							+ sousReq);
			Iterable<Map<String, String>> sousListeSubClass = TraiterOntologie
					.lanceRequeteSubClasses(sousReq, sparqlClient);

			// Les sous classes sont stockees
			if (sousListeSubClass.iterator().hasNext()) {
				sousReqTrouvee = true;
				System.out.print("  resultats -> ");
				for (Map<String, String> result : sousListeSubClass) {
					listeSubclass.add(result.get("name"));
					System.out.print(result.get("name") + " -- ");
				}
				System.out.println();
			}

			// Si on a trouve au moins un synonyme ou une sous classe
			if (sousReqTrouvee) {

				// On cree une sous requete amelioree par synonyme et par sous
				// classe. Le but est que, si randonnee a pour synonymes
				// "balade en montagne" et "balade en foret", on ne cree pas une
				// sous requete "balade en montagne balade en foret" qui va
				// donner les termes "balade montagn foret" dans laquelle les
				// termes balade et foret ne sont plus contigus, et donc pas
				// amplifies dans le calcul des poids
				requeteAmelioree.put(sousReq, listePoids.get(0));
				for (String syno : listeSyno) {
					requeteAmelioree.put(syno, listePoids.get(0));
				}
				for (String subclass : listeSubclass) {
					requeteAmelioree.put(subclass, listePoids.get(0));
				}
				// On a stocke les synonymes et sous classes, on les oublie
				listeSyno.clear();
				listeSubclass.clear();

				// On refait un calcul de fenetres sur les mots restants
				sousReqPonderees = epurerFenetres(listeSousReq, listePoids,
						listeIndicesDebut, listeIndicesFin, sousReq);
				listeSousReq = sousReqPonderees.getSousRequetes();
				listePoids = sousReqPonderees.getPoids();
				listeIndicesDebut = sousReqPonderees.getIndicesDebut();
				listeIndicesFin = sousReqPonderees.getIndicesFin();

			} else {
				// La sous requete n'a servi a rien, on l'enleve de la liste a
				// traiter
				int indiceInutile = listeSousReq.indexOf(sousReq);
				// Si c'est un mot unique, il ne faut pas l'oublier totalement !
				if (listeIndicesDebut.get(indiceInutile) == listeIndicesFin
						.get(indiceInutile)) {
					requeteAmelioree
							.put(sousReq, listePoids.get(indiceInutile));
				}
				listeSousReq.remove(indiceInutile);
				listePoids.remove(indiceInutile);
				listeIndicesDebut.remove(indiceInutile);
				listeIndicesFin.remove(indiceInutile);
			}
		}

		// On a traite synonymes et sous classes ; maintenant on va traiter les
		// instances. Ce n'est pas la meme chose : on veut aussi chercher les
		// instances des synonymes et les instances des sous classes. L'avantage
		// de le faire maintenant est que les labels n'ont pas encore ete
		// lemmatises ; or la recherche d'instances se base sur les types, qui
		// sont des mots de la forme LieuAdministratif. La lemmatisation
		// l'aurait decoupe en "lieu adminis", ce qui aurait tout gache...
		ArrayList<String> clesSousReq = new ArrayList<>(
				requeteAmelioree.keySet());
		for (String cle : clesSousReq) {
			System.out
					.println(">> Recherche des instances dans la sous requete : "
							+ cle);
			Iterable<Map<String, String>> instances = lanceRequeteInstancesClasse(
					cle, sparqlClient);

			// Les instances sont stockees dans la requete amelioree, avec le
			// meme poids que leur classe
			if (instances.iterator().hasNext()) {
				sousReqTrouvee = true;
				System.out.print("  resultats -> ");
				for (Map<String, String> result : instances) {
					System.out.print(result.get("name") + " -- ");
					requeteAmelioree.put(result.get("name"),
							requeteAmelioree.get(cle));
				}
				System.out.println();
			}
		}

		return requeteAmelioree;
	}

	public static ResultatRequete traiterRequeteParOntologie(String requete,
			int nbNoeuds) {

		// Construction d'une requete "standard" depuis une requete "ontologie"
		Map<String, Integer> requeteAmelioree = construitRequeteStandardDepuisOntologie(requete);
		System.out.println(">> Notre requete amelioree : " + requeteAmelioree);

		// On peut l'executer
		try {
			ResultatRequete noeuds = resultatRequete(requeteAmelioree, nbNoeuds);
			return noeuds;

		} catch (Exception e) {
			System.err.println("Echec de la requete");
			e.printStackTrace();
			return null;
		}
	}

	private static void testerGestionFenetre() {
		// test de gererFenetres
		ArrayList<String> s = TraiterOntologie.gererFenetres(
				"essai de la gestion des fenetres").getSousRequetes();
		System.out
				.println("doit afficher :\nessai gestion fenetre\nessai gestion\ngestion fenetre\nessai\ngestion\nfenetre");
		System.out
				.println("#############################################################");

		for (int i = 0; i < s.size(); i++) {
			System.out.println(s.get(i));
		}
	}

	private static void testerRequeteSynonyme() {
		RequeteOntologie sparqlClient = new RequeteOntologie(
				"localhost:3030/space");
		Iterable<Map<String, String>> sortie = lanceRequeteSynonymes("Izard",
				sparqlClient);
		System.out.println("Affichage synonymes :");
		for (Map<String, String> mapSyno : sortie) {
			for (String cle : mapSyno.keySet()) {
				System.out.println(" - " + cle + " -> " + mapSyno.get(cle));
			}
		}
	}

	private static void testerRequeteSubclasses() {
		RequeteOntologie sparqlClient = new RequeteOntologie(
				"localhost:3030/space");
		Iterable<Map<String, String>> sortie = lanceRequeteSubClasses(
				"mammifère", sparqlClient);
		System.out.println("Affichage subclasses :");
		for (Map<String, String> mapSyno : sortie) {
			System.out.print("  liste : ");
			for (String cle : mapSyno.keySet()) {
				System.out.print(mapSyno.get(cle) + " -- ");
			}
			System.out.println();
		}
	}

	private static void testerRequeteInstance() {
		RequeteOntologie sparqlClient = new RequeteOntologie(
				"localhost:3030/space");
		Iterable<Map<String, String>> sortie = lanceRequeteInstancesClasse(
				"Forêt", sparqlClient);
		System.out.println("Affichage instances :");
		for (Map<String, String> mapSyno : sortie) {
			System.out.print("  liste : ");
			for (String cle : mapSyno.keySet()) {
				System.out.print(mapSyno.get(cle) + " -- ");
			}
			System.out.println();
		}
	}

	public static void main(String args[]) {

//		testerGestionFenetre();
//		testerRequeteSynonyme();
//		testerRequeteSubclasses();
//		testerRequeteInstance();

		GetBDD bdd = GetBDD.getInstance();
		ResultatRequete noeuds = traiterRequeteParOntologie("GR10 rando pyrénées",
				10);
		// Afficher les xpath des noeuds pertinents
		for (Noeud noeud : noeuds.getListeNoeuds()) {
			String xPath = "Collection/"
					+ bdd.recupererDocsFromId(noeud.getIdDocument()) + "\t"
					+ noeud.getxPath();
			System.out.println(xPath + " ---> Noeud " + noeud.getIdNoeud());
		}
		bdd.fermeConnexion();
	}

}
